#ifndef CVX_BOARD_H
#define CVX_BOARD_H

#include "cvxImage.h"
#include <vector>
#include "cvxMarker.h"

using std::vector;

//board interface
class CvxBoard
{
public:
	CvxBoard();
	virtual ~CvxBoard();

	virtual bool SetConfigure(const CvSize &size, const float unitLength);
//	virtual bool FindCorners(const IplImage *image, bool isTracking, const vector<CvxMarker>& preMarkers, vector<CvxMarker> &curMarker,
//							 vector<Point2f> &pts2d, vector<Point3f> &pts3d)const;

	virtual bool FindCorners(const IplImage *image, bool isTracking, const vector<CvxMarker>& preMarkers, 
							 vector<CvxMarker> &curMarker, vector<Point2f> &pts2d)const;

	virtual bool GetInsidePoints(const IplImage *image, vector<Point2f> &extremeCorners, 
					vector<Point2f> &pts2d)const;

	virtual void DrawCorners(const IplImage *image, const vector<Point2f> &pts)const;

	virtual float GetUnitLength(void)const;
	virtual CvSize GetPatternSize(void)const;
	virtual void Get3Dpts(vector<Point3f> &pts3d) const;

	

protected:

};

//chessboard in opencv
class CvxChessboard: public CvxBoard
{
public:

	CvxChessboard();
	~CvxChessboard();
	
	//inside marker position is valid area
	bool SetConfigure(const CvSize &size, const float unitLength);

	bool FindCorners(const IplImage *image, bool isTracking, const vector<CvxMarker>& preMarkers, 
					 vector<CvxMarker> &curMarker, vector<Point2f> &pts2d)const;

	bool GetInsidePoints(const IplImage *image, vector<Point2f> &extremeCorners, 
						 vector<Point2f> &pts2d)const;

	void DrawCorners(const IplImage *image, const vector<Point2f> &pts)const;

	float GetUnitLength(void)const;
	
	CvSize GetPatternSize(void)const;
	
	void Get3Dpts(vector<Point3f> &pts3d) const;	

private:
	CvSize m_size;
	float  m_squareLen;
	vector<Point3f> m_pts3d;
	vector<Point2f> m_pts2d;   //z == 0
};


/************************************************************************/
/* 
	marker chessboard to speed up corner detection
*/
/************************************************************************/
class CvxMarkerChessboard : public CvxBoard
{
public:
	CvxMarkerChessboard();
	~CvxMarkerChessboard();

	bool SetConfigure(const CvSize &size, const float unitLength);
	bool SetMarkerCorners(float markerLength);

	bool FindCorners(const IplImage *image, bool isTracking, const vector<CvxMarker>& preMarkers, 
					 vector<CvxMarker> &curMarker, vector<Point2f> &pts2d)const;

	bool GetInsidePoints(const IplImage *image, vector<Point2f> &extremeCorners, 
						 vector<Point2f> &pts2d)const;

	void DrawCorners(const IplImage *image, const vector<Point2f> &pts)const;

	float GetUnitLength(void)const;
	CvSize GetPatternSize(void)const;
	void Get3Dpts(vector<Point3f> &pts3d) const;	

	vector<Point3f> m_markerCorners3d;    // 4 * 4

private:
	CvSize m_size;
	float  m_squareLen;
	vector<Point2f> m_markerCenters;    //physical position of marker centers
	vector<Point3f> m_pts3d;
	vector<Point2f> m_pts2d;            //z == 0	

private:
	static void GetThreshold(const CvSize &imageSize, const CvSize &boardSize, int &thMax, int &thMin);
};


/************************************************************************/
/* 
	marker chessboard expand.
	It use most-outside chessboard corners as well as insider cornders.
*/
/************************************************************************/
class CvxMarkerChessboardExp : public CvxBoard
{
public:
	CvxMarkerChessboardExp();
	~CvxMarkerChessboardExp();

	bool SetConfigure(const CvSize &size, const float unitLength);
	bool SetMarkerCorners(float markerLength);
	
	bool FindCorners(const IplImage *image, bool isTracking, const vector<CvxMarker>& preMarkers, 
		vector<CvxMarker> &curMarker, vector<Point2f> &pts2d)const;

	bool GetInsidePoints(const IplImage *image, vector<Point2f> &extremeCorners, 
		vector<Point2f> &pts2d)const;

	void DrawCorners(const IplImage *image, const vector<Point2f> &pts)const;

	float GetUnitLength(void)const;
	CvSize GetPatternSize(void)const;
	void Get3Dpts(vector<Point3f> &pts3d) const;


	vector<Point3f> m_markerCorners3d;    // 4 * 4

private:
	CvSize m_size;
	float  m_squareLen;
	vector<Point2f> m_markerCenters;    //physical position of marker centers
	vector<Point3f> m_pts3d;
	vector<Point2f> m_pts2d;            //z == 0	
};



#endif